/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hw2;

import java.util.Stack;

/**
 *
 * @author Sanya & Avishay
 */

public class Furniture {

    private int currSX;
    private int currSY;
    private int currEX;
    private int currEY;
    private int initSX;
    private int initSY;
    private int initEX;
    private int initEY;
    private int targSX;
    private int targSY;
    private int targEX;
    private int targEY;
    private int currLenthX;
    private int currLenthY;
    private int targetRoom;
    private Stack stackMoves;
    private int num;
    private Rectangle initPos;
    private Rectangle currPos;
    private Rectangle targPos;
    private Stack stack;

    public Furniture(int initSX, int initSY, int initEX, int initEY, int targSX,
            int targSY, int targEX, int targEY) throws Exception {
        this.initSX = initSX;
        this.initSY = initSY;
        this.initEX = initEX;
        this.initEY = initEY;
        /*
        this.currSX = this.targSX = targSX;
        this.currSY = this.targSY = targSY;
        this.currEX = this.targEX = targEX;
        this.currEY = this.targEY = targEY;
        */
        this.currSX = this.initSX;
        this.currSY = this.initSY;
        this.currEX = this.initEX;
        this.currEY = this.initEY;
        this.targSX = targSX;
        this.targSY = targSY;
        this.targEX = targEX;
        this.targEY = targEY;
        
        
        this.initPos = new Rectangle(initSX, initSY, initEX, initEY);
        this.currPos = new Rectangle(currSX, currSY, currEX, currEY);
        this.targPos = new Rectangle(targSX, targSY, targEX, targEY);
        this.stackMoves = new Stack();
        int initLenX = Math.abs(initSX - initEX) + 1;
        int initLenY = Math.abs(initSY - initEY) + 1;
        int targLenX = Math.abs(targSX - targEX) + 1;
        int targLenY = Math.abs(targSY - targEY) + 1;
        currLenthX = targLenX;
        currLenthY = targLenY;
        if (targSX <= 10 && targSY <= 10) {
            this.targetRoom = 1;
        }
        else {
            if (targSY < 5 && targEY < 5) {
                this.targetRoom = 2;
                if (initLenX > 2 && initLenY > 2) {/*move through door*/
                    throw new Exception("INCORRECT LENGTH OF X OR Y");
                }
            } else if (targSY > 4 && targEY > 4) {
                this.targetRoom = 3;
                if (initLenX > 4 && initLenY > 4) {/*move through door*/
                    throw new Exception("INCORRECT LENGTH OF X OR Y");
                }
            } else {/*target coordinate in room 2 and 3 */
                throw new Exception("TARGET IN ROOM 2 AND 3");
            }
        }
        
        if ((initLenX != targLenX || initLenY != targLenY)
                && (initLenX != targLenY || initLenY != targLenX)) {
            throw new Exception("WRONG DIMENSION OF TARGET");
        }
    }
    
    public Furniture generateFurniture(Action action) throws Exception {
        Furniture fur = new Furniture(initSX, initSY, initEX, initEY, targSX, targSY, targEX, targEY);
        switch (action) {
            case MOVE_DOWN:
                fur.moveDown();
                break;
            case MOVE_UP:
                fur.moveUp();
                break;
            case MOVE_RIGHT:
                fur.moveR();
                break;
            case MOVE_LEFT:
                fur.moveL();
                break;
            case ROTATE_RIGHT:
                fur.rotateR();
                break;
            case ROTATE_LEFT:
                fur.rotateL();
                break;
            case NONE:
                break;
            default:
                throw new Exception("Invalid action specified");
        }

        return fur;
    }

    public void printM() {
        System.out.format("currSX=%d, currSY=%d, currEX=%d, currEY=%d, %n",
                currSX, currSY, currEX, currEY);
    }

    public int lenSX() {
        return Math.abs(initSX - currSX);
    }

    public int lenSY() {
        return Math.abs(initSY - currSY);
    }

    public int lenEX() {
        return Math.abs(initEX - currEX);
    }

    public int lenEY() {
        return Math.abs(initEY - currEY);
    }
    /*Operators*/

    public void moveR() {
        currSX++;
        currEX++;
        stackMoves.push("Move Left");
        System.out.println("moveR");
    }

    public void moveL() {
        currSX--;
        currEX--;
        stackMoves.push("Move Right");
        System.out.println("moveL");
    }

    public void moveUp() {
        currSY++;
        currEY++;
        stackMoves.push("Move Down");
        System.out.println("moveUP");
    }

    public void moveDown() {
        currSY--;
        currEY--;
        stackMoves.push("Move Up");
        System.out.println("moveDown");
    }

    private void swapLen() {
        int temp = currLenthX;
        currLenthX = currLenthY;
        currLenthY = temp;
    }
    //rotate around current "End" coordinate

    public void rotateR() {
        int t = currSX;
        currSX = currEX + currEY - currSY;
        currSY = currEY + t - currEX;
        swapLen();
        stackMoves.push("Rotate Left");
        System.out.println("rotateR");
    }

    /*public boolean rotateR() {
     * 
     * int tempSX = currEX + currEY - currSY;
     * int tempSY = currEY + currSX - currEX;
     * if (checkPoint(tempSX, tempSY, currEX, currSY)) {
     * currSX = tempSX;
     * currSY = tempSY;
     * swapLen();
     * stackMoves.push("Rotate Left");
     * System.out.println("rotateR");
     * return true;
     * }
     * return false;
     * }*/
    //rotate around current "End" coordinate 
    public void rotateL() {
        int t = currSX;
        currSX = currEX - (currEY - currSY);
        currSY = currEY - (t - currEX);
        swapLen();
        stackMoves.push("Rotate Right");
        System.out.println("rotateL");
    }

    /*Predicates*/
    public boolean canMoveR() {
        return checkPoint(currSX + 1, currSY, currEX + 1, currEY);
    }

    public boolean canMoveL() {
        return checkPoint(currSX - 1, currSY, currEX - 1, currEY);
    }

    public boolean canMoveUp() {
        return checkPoint(currSX, currSY + 1, currEX, currEY + 1);
    }

    public boolean canMoveDown() {
        return checkPoint(currSX, currSY - 1, currEX, currEY - 1);
    }

    public boolean canRotateR() {
        return checkPoint(currEX + currEY - currSY, currEY + currSX - currEX, currEX, currEY);
    }

    public boolean canRotateL() {
        return checkPoint(currEX - (currEY - currSY), currEY - (currSX - currEX), currEX, currEY);
    }

    /*check walls and range of coordinates*/
    public boolean checkPoint(int sx, int sy, int ex, int ey) {
        int temp;
        if (sy > ey) {
            temp = sy;
            sy = ey;
            ey = temp;
        }
        if (sx > ex) {
            temp = sx;
            sx = ex;
            ex = temp;
        }
        for (int y = sy; y <= ey; y++) {
            for (int x = sx; x <= ex; x++) {
                System.out.format("x= %d; y= %d %n", x,y);
                if ((x == 1 || x == 4 || x == 5 || x == 10) && y == 11) {
                    return false;
                }
                if (x < 1 || x > 20 || y < 1 || y > 10) {
                    
                    return false;
                }
            }
        }
        return true;
    }

    public boolean checkGoal(int x, int y) {
        if (currSX == initSX && currSY == initSY && currEX == initEX && currEY == initEY) {
            return true;
        }
        if (currEX == x && currEY == y) {
            return true;
        }
        return false;
    }
    
    public boolean goalReached() {
        if (currEX == targEX && currEY == targEY && currSX == targSX && currSY == targSY) {
            return true;
        }
        else {
            return false;
        }
    }

    /*Getters*/
    public int getCurrSX() {
        return currSX;
    }

    public int getCurrSY() {
        return currSY;
    }

    public int getCurrEX() {
        return currEX;
    }

    public int getCurrEY() {
        return currEY;
    }

    public int getInitSX() {
        return initSX;
    }

    public int getInitSY() {
        return initSY;
    }

    public int getInitEX() {
        return initEX;
    }

    public int getInitEY() {
        return initEY;
    }

    public int getTargSX() {
        return targSX;
    }

    public int getTargSY() {
        return targSY;
    }

    public int getTargEX() {
        return targEX;
    }

    public int getTargEY() {
        return targEY;
    }

    public int getCurrLenthX() {
        return currLenthX;
    }

    public int getCurrLenthY() {
        return currLenthY;
    }

    public Stack getStackMoves() {
        return stackMoves;
    }
    
    public int getCurrentRoom() {
        if (this.currSX <= 10) {
            return 1;
        }
        else {
            if (this.currSY <= 4) {
                return 2;
            }
            else {
                return 3;
            }
        }
    }

    public int getTargetRoom() {
        return targetRoom;

    }

    public Rectangle getInitPos() {
        return this.initPos;
    }

    public Rectangle getCurrPos() {
        return this.currPos;

    }

    public Rectangle getTargPos() {
        return this.targPos;

    }

    public boolean isClashingWith(Furniture other) {
        if (this.initPos.isClashingWith(other.getInitPos()) || this.currPos.isClashingWith(other.getCurrPos()) || this.targPos.isClashingWith(other.getTargPos())) {
            return true;
        } else {
            return false;
        }

    }

    public int check() {
        if (currSX == targSX ^ currSY == targSY ^ currEX == targEX ^ currEY == targEY) {
            return 1;
        }
        return 0;
    }
    //TODO exceptions: check coordinate and output massage to "addPanel.errorText"

    public void setNum(int num) {
        this.num = num;
    }

    public int getNum() {
        return this.num;
    }

    public void setCurrSX(int currSX) {
        this.currSX = currSX;
    }

    public void setCurrSY(int currSY) {
        this.currSY = currSY;
    }
    
}
